package com.qdd.freight.handler;

import com.qdd.freight.exception.NullAvailableParamsException;
import com.qdd.freight.mapper.DeliveryRegionMapper;
import com.qdd.freight.pojo.Delivery;
import com.qdd.freight.pojo.DeliveryRegion;
import com.qdd.freight.pojo.Ship;
import org.springframework.beans.factory.annotation.Autowired;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;

/**
 * @ClassName AbstractDeliveryHandler
 * @Description TODO
 * @Author yanpeihao
 * @Date 2019/12/23 14:34
 * @Version 1.0
 **/

abstract public class AbstractDeliveryHandler extends AbstractHandler {

    @Autowired
    private DeliveryRegionMapper deliveryRegionMapper;

    /**
     * 普通快递大于起步件数时，德邦，京东，顺丰件数计算运费公共方法
     *
     * @param delivery 快递对象
     * @param quantity 采购数量
     *                 大于起步件数：
     *                 总价格=首件价格+（采购数量-首件件数）/续重规格）*续重单价
     *                 （采购数量-首件件数）/续重规格 = 续重的数量
     */

    protected Double startingPriceCalculation(Integer quantity, Integer headWeight, Double headPrice,
                                              Integer extensionWeight, Double extensionPrice) {
        BigDecimal bQuantity = BigDecimal.valueOf(quantity);
        BigDecimal bHeadPrice = BigDecimal.valueOf(headPrice);
        BigDecimal bHeadWeight = BigDecimal.valueOf(headWeight);
        BigDecimal bExtensionWeight = BigDecimal.valueOf(extensionWeight);
        BigDecimal bExtensionPrice = BigDecimal.valueOf(extensionPrice);

        Double sumPrice = bHeadPrice.add((bQuantity.subtract(bHeadWeight)).divide(bExtensionWeight, 2).multiply(bExtensionPrice)).doubleValue();
        return sumPrice;
    }

    /**
     * 德邦，京东，顺丰重量计算运费公共方法
     *
     * @param delivery
     * @param sumWeight 总重量
     *                  总价格=  首重价格+（总重量-首重重量）/续重规格）*续重单价
     *                  （整箱总重量-首重重量）/续重规格 = 续重的数量
     * @return
     */
    protected Double weightFreightRate(Double sumWeight, Integer headWeight, Double headPrice,
                                       Integer extensionWeight, Double extensionPrice) {
        BigDecimal bSumWeight = BigDecimal.valueOf(sumWeight);
        BigDecimal bHeadPrice = BigDecimal.valueOf(headPrice);
        BigDecimal bHeadWeight = BigDecimal.valueOf(headWeight);
        BigDecimal bExtensionWeight = BigDecimal.valueOf(extensionWeight);
        BigDecimal bExtensionPrice = BigDecimal.valueOf(extensionPrice);
        Double sumPrice = bHeadPrice.add((bSumWeight.subtract(bHeadWeight)).divide(bExtensionWeight, 2, BigDecimal.ROUND_UP).multiply(bExtensionPrice)).doubleValue();
        return sumPrice;
    }

    /**
     * 获取可用的计算参数
     *
     * @param ship      入参其实现类,快递或物流对象
     * @param ifLevel   是否存在级别设置标志位,0-不存在,1-存在
     * @param shipId    快递/物流id
     * @param consignee
     * @return
     * @throws NullAvailableParamsException
     */
    protected Map<String, Object> getAvailableParams(Ship ship, Integer shipId, String consignee) throws NullAvailableParamsException {
        Delivery delivery = (Delivery) ship;
        //1.获取物流对象对象
        Map<String, Object> paramMap = new HashMap<>();
        //2.获取计价方式
        Integer startingWeight = delivery.getStartingWeight();//起步重量
        Double startingPrice = delivery.getStartingPrice();//起步价格
        Integer headWeight = delivery.getHeadWeight();//首重重量
        Double headPrice = delivery.getHeadPrice();//首重价格
        Integer extensionWeight = delivery.getExtensionWeight();//续重规格
        Double extensionPrice = delivery.getExtensionPrice();//续重单价

        //3.以关联的物流Id和到货地区为条件，获取该收获地址下是否存在特殊价格设置
        String[] receiverArr = consignee.split("-");//到货地区
        String receiverAddr = receiverArr[1];//当前收件地址
        //获取该物流对象下所有关联的特殊计价地区清单
        Example example = new Example(DeliveryRegion.class);
        example.createCriteria().andEqualTo("deliveryId", shipId);
        DeliveryRegion deliveryRegion = deliveryRegionMapper.selectOneByExample(example);
        //4.如果存在特殊价格设置则以特殊价格进行运费计算
        //4.1判断特殊计价清单中是否包含当前收货地址(注意省市区的层级所属关系,判断包含而不是等于)
        boolean isInclude = false;//默认没有禁运设置
        //判断当前收件地址是否以禁运清单中的地址开头
        if (deliveryRegion != null) {
            String regionArr = deliveryRegion.getConsignee();
            isInclude = Stream.of(regionArr).anyMatch(receiverAddr::startsWith);
        }
        //4.2如果存在,使用特殊计价覆盖
        if (isInclude) {
            startingWeight = delivery.getStartingWeight();//起步重量
            startingPrice = delivery.getStartingPrice();//起步价格
            headWeight = delivery.getHeadWeight();//首重重量
            headPrice = delivery.getHeadPrice();//首重价格
            extensionWeight = delivery.getExtensionWeight();//续重规格
            extensionPrice = delivery.getExtensionPrice();//续重单价
        }
        //5.对计价参数进行数据校验
        if (startingWeight == null || startingPrice == null
                || headWeight == null || headPrice == null
                || extensionWeight == null || extensionPrice == null) {
            throw new NullAvailableParamsException("未获取到正确的计数阶梯数据。");
        }
        paramMap.put("startingWeight", startingWeight);
        paramMap.put("startingPrice", startingPrice);
        paramMap.put("headWeight", headWeight);
        paramMap.put("headPrice", headPrice);
        paramMap.put("extensionWeight", extensionWeight);
        paramMap.put("extensionPrice", extensionPrice);
        return paramMap;
    }

}
